/*
 * @Author: 李天惊 uf_lee@163.com
 * @Date: 2025-04-12 22:01:56
 * @LastEditors: 李天惊 uf_lee@163.com
 * @LastEditTime: 2025-04-13 14:20:39
 * @FilePath: \leemvvm\lee-mvvm\src\runtime\index.ts
 * Copyright (c) 2025 by ${git_name_email}, All Rights Reserved.
 */

// 导入用于创建响应式对象的函数
import { reactive } from "../core/reactivity/reactive";
// 导入用于创建副作用函数的函数
import { effect } from "../core/reactivity/effect";
// 导入用于创建虚拟DOM节点的函数
import { h } from "../core/renderer/h";
// 导入生命周期函数
import {
  callMounted,
  callUpdated,
  callUnmounted,
} from "../core/lifecycle/lifecycle";

// 创建组件上下文缓存（组件名 -> 响应式数据）
const instanceCache = new Map<string, any>();
const renderCache = new Map<string, string>(); // 缓存渲染后的 HTML，避免重复渲染

/**
 * 编译模板函数：处理插值和子组件
 */
function compileTemplate(
  template: string,
  ctx: Record<string, any>,
  components: Record<string, any> = {},
  stack: string[] = [] // 组件调用栈（用于防止无限递归）
): string {
  // 替换插值表达式
  let html = template.replace(/\{\{\s*(.+?)\s*\}\}/g, (_, expr) => {
    try {
      return new Function("ctx", `with(ctx) { return ${expr} }`)(ctx);
    } catch {
      return "";
    }
  });

  // 渲染子组件
  for (const name in components) {
    const tagRegex = new RegExp(`<${name}\\s*\\/?>`, "g");

    // ⚠️ 如果栈中已存在该组件，说明出现递归渲染 → 跳过
    if (stack.includes(name)) {
      // console.warn(`检测到组件 ${name} 的递归渲染，已跳过避免栈溢出`);
      continue;
    }

    // 创建一个虚拟DOM节点，用于替换模板中的子组件标签
    const subComp = components[name];

    // 获取子组件上下文（首次创建并缓存）
    let subCtx = instanceCache.get(name);
    // 如果没有缓存，则创建并缓存
    if (!subCtx) {
      // 首次创建并缓存
      subCtx = subComp.setup ? subComp.setup() : {};
      // 触发响应式更新
      instanceCache.set(name, subCtx);
    }

    // 渲染子组件的 HTML
    const subHTML = `<div id="${name}-container">${compileTemplate(
      subComp.template,
      subCtx,
      components,
      [...stack, name]
    )}</div>`;

    // 如果缓存的 HTML 和当前 HTML 不同，则需要更新
    if (renderCache.get(name) !== subHTML) {
      html = html.replace(tagRegex, subHTML);
      renderCache.set(name, subHTML); // 缓存渲染结果
    }
  }

  return html;
}

/**
 * 编译模板字符串，替换模板中的表达式
 * @param template - 模板字符串
 * @param ctx - 上下文对象，用于解析表达式
 * @param components - 组件对象，用于解析模板中的组件
 * @returns 编译后的模板字符串
 */
// function compileTemplate(
//   template: string,
//   ctx: Record<string, any>,
//   components: Record<string, any> = {},
//   stack: string[] = [] // 组件调用栈（用于防止无限递归）
// ): string {
//   // 1. 替换插值表达式 {{ xxx }}
//   let html = template.replace(/\{\{\s*(.+?)\s*\}\}/g, (_, expr) => {
//     try {
//       // 使用 Function + with 实现简单表达式解析
//       return new Function("ctx", `with(ctx) { return ${expr} }`)(ctx);
//     } catch {
//       return "";
//     }
//   });
//   // 2. 渲染子组件
//   for (const name in components) {
//     const tagRegex = new RegExp(`<${name}\\s*\\/?>`, "g"); // 创建正则表达式

//     // ⚠️ 如果栈中已存在该组件，说明出现递归渲染 → 跳过
//     if (stack.includes(name)) {
//       console.warn(`检测到组件 ${name} 的递归渲染，已跳过避免栈溢出`);
//       continue;
//     }

//     const subComp = components[name]; // 获取子组件对象

//     // 获取子组件上下文（首次创建并缓存）
//     // let subCtx = instanceCache.get(name);
//     // if (!subCtx) {
//     //   subCtx = subComp.setup ? subComp.setup() : {};
//     //   instanceCache.set(name, subCtx);
//     // }

//     // // 渲染子组件的 HTML
//     // const subHTML = `<div id="${name}-container">${compileTemplate(
//     //   subComp.template,
//     //   subCtx,
//     //   components,
//     //   [...stack, name]
//     // )}</div>`;

//     // // 如果缓存的 HTML 和当前 HTML 不同，则需要更新
//     // if (renderCache.get(name) !== subHTML) {
//     //   html = html.replace(tagRegex, subHTML);
//     //   renderCache.set(name, subHTML); // 缓存渲染结果
//     // }

//     // ✅ 如果已有缓存，直接复用，否则调用 setup 并缓存
//     if (!instanceCache.has(name)) {
//       const subCtx = subComp.setup ? subComp.setup() : {};
//       instanceCache.set(name, subCtx);

//       // 触发响应式更新
//       effect(() => {
//         const container = document.querySelector(`${name}-container`);
//         console.log("container", container);
//         if (container) {
//           container.innerHTML = compileTemplate(
//             subComp.template,
//             subCtx,
//             components,
//             [...stack, name] // 更新栈，避免嵌套自己
//           );
//         }
//       });
//     }
//     // 使用缓存的子组件上下文替换模板中的子组件标签
//     const subCtx = instanceCache.get(name);
//     // 创建一个虚拟DOM节点，用于替换模板中的子组件标签
//     // const subHTML = "";
//     console.log("subComp.template", subComp.template);
//     console.log("subCtx", subCtx);
//     const subHTML = `<div is-sub-component id="${name}-container">${compileTemplate(
//       subComp.template,
//       subCtx,
//       components,
//       [...stack, name] // 更新栈，避免嵌套自己
//     )}</div>`;
//     // const subCtx = subComp.setup ? subComp.setup() : {}; // 获取子组件的setup函数的返回值，如果没有setup函数，则返回空对象
//     // const subHTML = compileTemplate(subComp.template, subCtx); // 使用compileTemplate函数编译子组件的模板
//     html = html.replace(tagRegex, subHTML); // 替换模板中的子组件标签为子组件的渲染结果
//   }

//   return html;
// }

/**
 * 创建一个应用程序实例的函数
 * @param rootComponent - 根组件，通常是一个Vue组件对象
 * @returns 返回应用程序实例，包含挂载方法
 */
export function createApp(rootComponent: any) {
  return {
    // 挂载方法
    mount(container: HTMLElement) {
      // 简单地渲染组件
      let isMounted = false;
      // 用于保存上一次渲染的元素
      let prevEl: HTMLElement | null = null;

      // 创建一个响应式对象，用于存储组件的属性和状态
      const ctx = rootComponent.setup ? rootComponent.setup() : {};

      const components = rootComponent.components || {}; // 获取组件的子组件对象

      effect(() => {
        // 创建一个虚拟DOM节点
        const el = document.createElement("div");

        // 调用组件的render方法，获取组件的渲染结果
        // const content = rootComponent.render ? rootComponent.render(ctx) : "";

        const content = rootComponent.template // 使用模板字符串替换模板中的表达式
          ? compileTemplate(rootComponent.template, ctx, components) // 使用模板字符串替换模板中的表达式
          : rootComponent.render?.(ctx) ?? ""; // 使用render方法获取组件的渲染结果

        // 使用innerHTML设置元素的HTML内容
        el.innerHTML = content;

        // 判断是否是第一次渲染
        if (!isMounted) {
          // 第一次渲染时，直接将结果添加到容器中
          container.appendChild(el);
          // 标记为已挂载
          isMounted = true;
          callMounted(); // 组件挂载时调用 onMounted
        } else if (prevEl) {
          container.replaceChild(el, prevEl); // 后续渲染时，替换掉之前的结果
        }
        prevEl = el; // 更新上一次渲染的元素
        callUpdated(); // 组件更新时调用 onUpdated
      });
    },
  };
}

// 在卸载时触发生命周期钩子
export function unmount(container: HTMLElement, component: any) {
  callUnmounted(); // 调用 onUnmounted 钩子
  container.innerHTML = ""; // 清空容器
}
